package basis.idnr;

import java.io.Serializable;

/**
 * Diese Klasse dient als Oberklasse fuer die ISBN-Klassen.
 * 
 * Datei: Identifikationsnummer.java                   
 * Datum: 19.11.2011   
 *                  
 * @author Alexander Bredo 
 * @version 0.3
 */
public abstract class Identifikationsnummer implements Serializable
{
  private static final long serialVersionUID = 6943240645508786355L;


  /**
   * Konvertiert einen ISBN-String in eine Zahl
   */
  public static long gibZahl (String isbn)
  {
    String isbnOhneSz = gibISBNZahlenketteOhneSonderzeichen (isbn);

    if (isbnOhneSz.isEmpty ())
    {
      throw new IllegalArgumentException (
          "Leere Zeichenketten oder ungueltige Zeichen sind nicht erlaubt.");
    }

    Long isbnZahl = new Long (isbnOhneSz);
    return isbnZahl;
  }
  
  
  /**
   * Entfernt alle ueberfluessigen Zeichen aus der ISBN-Zeichenfolge
   */
  protected static String gibISBNZahlenketteOhneSonderzeichen (String isbn)
  {
    StringBuilder sb = new StringBuilder ();

    for (int i = 0; i < isbn.length (); i++)
    {
      char zeichen = isbn.charAt (i);
      if (istGueltigeISBNZahl (zeichen))
      {
        sb.append (zeichen);
      }
    }
    return sb.toString ();
  }
  
  
  /**
   * Prueft ein Zeichen, ob es ein gueltiges ISBN-Zeichen ist
   */
  private static boolean istGueltigeISBNZahl (char zeichen)
  {
    final char[] gueltigeISBNZahlen = { '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9' };
    for (int i = 0; i < gueltigeISBNZahlen.length; i++)
    {
      if (gueltigeISBNZahlen[i] == zeichen)
      {
        return true;
      }
    }
    return false;
  }
  
  
  /**
   * Gibt die Laenge der ISBN-Nummer zurueck
   */
  protected static int gibLaenge (long isbn)
  {
    double tmp1 = Math.log10 (isbn);
    int tmp2 = (int) Math.floor (tmp1) + 1;
    return tmp2;
  }
  
  
  /**
   * Gibt eine Nummer mit einer bestimmten Anzahl fuehrender Nullen aus.
   */
  protected static String gibZahlMitFuehrenderNull (long zahl, int laenge)
  {
    String zeichenkette = String.valueOf (zahl);
    while (zeichenkette.length () < laenge)
    {
      zeichenkette = "0" + zeichenkette;
    }
    return zeichenkette;
  }
  
  
  /**
   * Prueft die ISBN-Nummer auf eine gueltige Laenge
   */
  protected boolean istGueltigeLaenge (long isbn)
  {
    int laenge = gibLaenge (isbn);
    int gueltigeLaenge = gibGueltigeLaenge ();
    
    if ((laenge == gueltigeLaenge) || 
        (laenge == gueltigeLaenge - 1))
    {
      return true;                      /* Sonderfall: beginnt mit 0  */
    }
    else
    {
      return false;
    }
  } 
  
  
  /**
   * Gibt die gueltige Laenge einer Identifikationsnummer zurueck.
   * Diese Methode muss in der konkreten Implementierung ueberschrieben 
   * werden, da Java sie nicht als abstract markieren kann.
   * @return
   */
  protected abstract int gibGueltigeLaenge ();

  public abstract long toLong();
  
}
